<template>
    <div class="parent">
        <div id="container"></div>
        <div id="controls"></div>
    </div>
</template>
<script setup lang="ts"> 
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { onMounted } from 'vue';
import {GUI} from 'three/examples/jsm/libs/lil-gui.module.min.js';


onMounted(()=>{
    const scene = new THREE.Scene();
    scene.background = new THREE.Color('black');
    const fov = 45;
	const aspect = 2;
	const near = 0.1;
	const far = 100;
    const camera = new THREE.PerspectiveCamera(fov,aspect,near,far);
    camera.position.set(0, 10, 20);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.getElementById('container')?.appendChild(renderer.domElement);

    const controls = new OrbitControls(camera, renderer.domElement);
    controls.target.set(0, 5, 0);
    controls.update();

    {

		const planeSize = 40;

		const loader = new THREE.TextureLoader();
		const texture = loader.load( '/pngs/checker.png' );
		texture.wrapS = THREE.RepeatWrapping;
		texture.wrapT = THREE.RepeatWrapping;
		texture.magFilter = THREE.NearestFilter;
		texture.colorSpace = THREE.SRGBColorSpace;
		const repeats = planeSize / 2;
		texture.repeat.set( repeats, repeats );

		const planeGeo = new THREE.PlaneGeometry( planeSize, planeSize );
		const planeMat = new THREE.MeshPhongMaterial( {
			map: texture,
			side: THREE.DoubleSide,
		} );
		const mesh = new THREE.Mesh( planeGeo, planeMat );
		mesh.rotation.x = Math.PI * - .5;
		scene.add( mesh );
    }

    {
        const cubeSize = 4;
        const cubeGeo = new THREE.BoxGeometry( cubeSize, cubeSize, cubeSize );
        const cubeMat = new THREE.MeshPhongMaterial( { color: '#8AC' } );
        const mesh = new THREE.Mesh( cubeGeo, cubeMat );
        mesh.position.set( cubeSize + 1, cubeSize / 2, 0 );
        scene.add( mesh );
    }

    {
        const sphereRadius = 3;
        const sphereWidthDivisions = 32;
        const sphereHeightDivisions = 16;
        const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions );
        const sphereMat = new THREE.MeshPhongMaterial( { color: '#CA8' } );
        const mesh = new THREE.Mesh( sphereGeo, sphereMat );
        mesh.position.set( - sphereRadius - 1, sphereRadius + 2, 0 );
        scene.add( mesh );
    }

    class ColorGUIHelper {
        private object:any;
        private prop:any;
        constructor( object:any, prop:any) {
            this.object = object;
            this.prop = prop;
        }
        get value() {
            return `#${this.object[ this.prop ].getHexString()}`;
        }
        set value( hexString ) {
            this.object[ this.prop ].set( hexString );
        }
    }

    {
        const skyColor = 0xB1E1FF; // light blue
        const groundColor = 0xB97A20; // brownish orange
        const intensity = 1;
        const light = new THREE.HemisphereLight( skyColor, groundColor, intensity );
        scene.add( light );

        const gui = new GUI({container:document.getElementById("controls")!!});
        gui.addColor( new ColorGUIHelper( light, 'color' ), 'value' ).name( 'skyColor' );
        gui.addColor( new ColorGUIHelper( light, 'groundColor' ), 'value' ).name( 'groundColor' );
        gui.add( light, 'intensity', 0, 5, 0.01 );
    }

    
	function resizeRendererToDisplaySize( renderer: THREE.WebGLRenderer ) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if ( needResize ) {
            renderer.setSize( width, height, false );
        }
        return needResize;
    }

    function render() {
        if ( resizeRendererToDisplaySize( renderer ) ) {
            const canvas = renderer.domElement;
            camera.aspect = canvas.clientWidth / canvas.clientHeight;
            camera.updateProjectionMatrix();
        }
        renderer.render( scene, camera );
        requestAnimationFrame( render );
    }
    requestAnimationFrame( render );
    
});

</script>

<style scoped> 
.parent {
    position: relative;
    width: 100%;
    height: 100%;
}

.parent > * {
    position: absolute;
}

#controls {
    right: 0;
}
</style>